package com.seckill.service.impl;

import com.seckill.common.error.BusinessException;
import com.seckill.common.error.ErrorEnum;
import com.seckill.dao.OrderDOMapper;
import com.seckill.dao.SequenceDOMapper;
import com.seckill.dao.StockLogDOMapper;
import com.seckill.domain.OrderDO;
import com.seckill.domain.SequenceDO;
import com.seckill.domain.StockLogDO;
import com.seckill.model.dto.ItemDTO;
import com.seckill.model.dto.OrderDTO;
import com.seckill.service.ItemService;
import com.seckill.service.OrderService;
import com.seckill.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @author lill
 * @date 2019-06-24
 */
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private ItemService itemService;

    @Autowired
    private UserService userService;

    @Autowired
    private OrderDOMapper orderDOMapper;

    @Autowired
    private SequenceDOMapper sequenceDOMapper;

    @Autowired
    private StockLogDOMapper stockLogDOMapper;

    private static final int MAX_AMOUNT = 99;
    private static final int MIN_AMOUNT = 1;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderDTO createOrder(Integer userId, Integer itemId, Integer promoId, Integer amount, String stockLogId) {
        //1.校验下单状态（用户是否合法，下单商品是否存在，购买数量是否正确）
        ItemDTO itemDTO = itemService.getItemByIdInCache(itemId);
        if (null == itemDTO) {
            throw new BusinessException((ErrorEnum.VALIDATION_REQUEST_PARAM_ERROR), "商品不存在");
        }
        if (amount < MIN_AMOUNT || amount > MAX_AMOUNT) {
            throw new BusinessException(ErrorEnum.VALIDATION_REQUEST_PARAM_ERROR, "数量信息不正确");
        }

        // 3.订单入库
        OrderDTO orderDTO = new OrderDTO();
        orderDTO.setUserId(userId);
        orderDTO.setItemId(itemId);
        orderDTO.setAmount(amount);
        if (null != promoId) {
            orderDTO.setItemPrice(itemDTO.getPromoDTO().getPromoItemPrice());
        } else {
            orderDTO.setItemPrice(itemDTO.getPrice());
        }
        orderDTO.setPromoId(promoId);
        orderDTO.setOrderPrice(orderDTO.getItemPrice().multiply(BigDecimal.valueOf(amount)));

        // 生成交易流水号，订单号
        orderDTO.setId(generatorOrderNo());
        OrderDO orderDO = convertFromOrderModel(orderDTO);
        orderDOMapper.insertSelective(orderDO);

        // 商品销量增加
        itemService.increaseSales(itemId, amount);

        // 减 redis 库存，
        boolean result = itemService.decreaseStock(itemId, amount);
        if (!result) {
            throw new BusinessException(ErrorEnum.STOCK_NOT_ENOUGH);
        }

        // 设置库存流水
        StockLogDO stockLogDO = stockLogDOMapper.selectByPrimaryKey(stockLogId);
        if (null == stockLogDO) {
            throw new BusinessException(ErrorEnum.TRANSACTION_FAIL);
        }
        stockLogDO.setStatus(2);
        stockLogDOMapper.updateByPrimaryKeySelective(stockLogDO);

        // 本次事务提交成功后执推送扣减库存的消息
//        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
//            @Override
//            public void afterCommit() {
//                itemService.asynchronousDecreaseStock(itemId, amount);
//            }
//        });

        // 异步更新库存
//        boolean mqResult = itemService.asynchronousDecreaseStock(itemId, amount);
//        if (!mqResult) {
//            // 更新库存失败
//            itemService.increaseDecreaseStock(itemId, amount);
//            throw new BusinessException(ErrorEnum.MQ_SEND_FAIL);
//        }
        // 返回前端
        return orderDTO;
    }


    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public String generatorOrderNo() {
        //1.订单号有16位
        StringBuilder stringBuilder = new StringBuilder();
        //前8位为时间信息，年月日
        LocalDateTime now = LocalDateTime.now();
        String nowDate = now.format(DateTimeFormatter.ISO_DATE).replace("-", "");
        stringBuilder.append(nowDate);

        //2.中间六位为自增序列
        //获取当前sequence

        SequenceDO sequenceDO = sequenceDOMapper.selectByPrimaryKey("order_info");
        if (null == sequenceDO) {
            sequenceDO = new SequenceDO();
            sequenceDO.setName("order_info");
            sequenceDO.setCurrentValue(100);
            sequenceDO.setStep(2);
            sequenceDOMapper.insert(sequenceDO);
        }
        int sequence = sequenceDO.getCurrentValue();
        sequenceDO.setCurrentValue(sequenceDO.getCurrentValue() + sequenceDO.getStep());
        sequenceDOMapper.updateByPrimaryKeySelective(sequenceDO);
        //凑足六位
        String sequenceStr = String.valueOf(sequence);
        for (int i = 0; i < 6 - sequenceStr.length(); i++) {
            stringBuilder.append(0);
        }
        stringBuilder.append(sequenceStr);

        //3.最后两位分库分表位
        stringBuilder.append("00");
        return stringBuilder.toString();
    }

    /**
     * OrderDTO 转为 OrderDO
     *
     * @param orderDTO
     * @return
     */
    private OrderDO convertFromOrderModel(OrderDTO orderDTO) {
        if (null == orderDTO) {
            return null;
        }
        OrderDO orderDO = new OrderDO();
        BeanUtils.copyProperties(orderDTO, orderDO);
        return orderDO;
    }
}
